package com.zys.el.user.service.Impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.zys.el.core.service.impl.CrudServiceImpl;
import com.zys.el.time.entity.AbsorbedDeal;
import com.zys.el.time.entity.Deal;
import com.zys.el.time.vojo.Result;
import com.zys.el.user.client.AbsorbedDealClient;
import com.zys.el.user.client.DealClient;
import com.zys.el.user.config.po.Start;
import com.zys.el.user.config.po.SynthesizeResult;
import com.zys.el.user.po.Target;
import com.zys.el.user.po.TargetUser;
import com.zys.el.user.po.Task;
import com.zys.el.user.service.*;
import com.zys.el.user.util.TunxunApi.DiretSimilar;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.xm.Similarity;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class TargetServiceImpl extends CrudServiceImpl<Target> implements ITargetService {

    @Autowired
    private ITargetUserService targetUserService;
    @Autowired
    private IUserService userService;
    @Autowired
    private ITaskService taskService;
    @Autowired
    private ITargetService targetService;
    @Resource
    private ISynthesizeService service;
    @Resource
    private RedisTemplate redisTemplate;
    @Autowired
    private DealClient dealClient;
    @Autowired
    private AbsorbedDealClient absorbedDealClient;

    @Override
    public List<Target> getTargetByName(String name) {
        QueryWrapper<Target> qw = new QueryWrapper<>();
        qw.eq("name_", name);
        return getBaseMapper().selectList(qw);
    }

    @Override
    public List<String> getTargetNameByType(Long type) {
        QueryWrapper<Target> qw = new QueryWrapper<>();
        qw.eq("type_", type);
        List<Target> targets = getBaseMapper().selectList(qw);
        return targets.stream().map(Target::getName).collect(Collectors.toList());
    }

    @Override
    public List<Target> selectListNoDelete() {

        QueryWrapper<Target> qw = new QueryWrapper<>();
        qw.eq("delete_", 0);
        return getBaseMapper().selectList(qw);
    }

    @Override
    public int finishTargetByUserId(Long userId) throws JsonProcessingException {
        TargetUser targetUser = targetUserService.selectTargetByUserId(userId);
        if (targetUser == null) return -1;
        Target target = this.getById(targetUser.getTargetId());
        if (target.getFanish() == 1) return 2;
        if (target == null) return -1;
        target.setFanish(1);
        target.setFanishUpdate(new Date());
        SynthesizeResult synthesizeByForth = service.getSynthesizeByForth(userId);
        synthesizeByForth.setReadySize(service.getSynthesizeByReady());
        redisTemplate.opsForValue().set("SY" +userId,JSON.toJSONString(synthesizeByForth));
        boolean b = this.saveOrUpdate(target);
        if (b == false) return -1;
        return 1;
    }

    @Override
    public List<Target> selectListByNameToOrderByLike(String name) {
        QueryWrapper<Target> qw = new QueryWrapper<>();
        qw.eq("name_", name);
        qw.orderByDesc("like_");
        List<Target> targets = this.baseMapper.selectList(qw);
        return targets;
    }

    @Override
    public Long SaveOrUpdateTarget(Target target, Long userId) {
//        System.out.println(target + "[][]");
//        //用户和目标
//        QueryWrapper<TargetUser> qw = new QueryWrapper<>();
//        qw.eq("user_id_", userId);
//        TargetUser targetUser = targetUserService.getOne(qw);
//        System.out.println("userId:" + userId);
//
//        if (targetUser == null) {
//            targetUser = new TargetUser();
//            //如果不存在中间表，那就插入中间表和目标表
//            boolean b = this.saveOrUpdate(target);
//            if (b == false) return 0l;
//            System.out.println(target.getId());
//            targetUser.setTargetId(target.getId());
//            targetUser.setUserId(userId);
//            targetUserService.save(targetUser);
//        } else {//如果存在中间表，那就看看其目标是否存在
//            System.out.println(targetUser);
//            Long targetId = targetUser.getTargetId();
//            Target targetOne = this.getById(targetId);
//            System.out.println(targetOne);
//            if (targetOne != null && targetOne.getDelete() == 0) {//如果存在
//                if (targetOne.getName().equals(target.getName())) {
//                    return targetOne.getId();
//                } else {
//                    //更改为1表示删除
//                    targetOne.setDelete(1);
//                    this.saveOrUpdate(targetOne);
//                    System.out.println(target);
//                    //增加目标表
//                    boolean b = this.saveOrUpdate(target);
//                    if (b == false) return 0l;
//
//                    //增加中间表
////                    targetUser.setTargetId(target.getId());
//                    targetUser.setDelete(1);//逻辑删除
//                    targetUserService.saveOrUpdate(targetUser);
//                    targetUser.setTargetId(target.getId());//在插入
//                    targetUser.setDelete(0);
//                    targetUserService.save(targetUser);
//                }
//
//            } else {
//                //增加目标表
//                boolean b = this.saveOrUpdate(target);
//                if (b == false) return 0l;
//                //增加中间表
//                targetUser.setTargetId(target.getId());
//                targetUserService.save(targetUser);
//            }
//
//        }
//
//        return target.getId();
        // 目标和用户id
        // 用户目标 第一次创建 修改
        // 判断是否是第一次创建：根据用户id查询中间表是否存在，如果不存在则是第一次
        TargetUser one = targetUserService.query().eq("user_id_", userId).eq("delete_", 0).one();
        if (one == null) { // 第一次创建，插入中间表、插入目标表
            target.setCreateTime(new Date());
            this.saveOrUpdate(target);//target就有id了

            TargetUser targetUser = new TargetUser();
            targetUser.setDelete(0);
            targetUser.setTargetId(target.getId());
            targetUser.setUserId(userId);
            targetUserService.save(targetUser);

        } else {
            //如果不是第一次，就先删除目标表和中间表-》通过用户id获取中间表，然后通过中间表删除目标表=逻辑删除

            Target t = this.getById(one.getTargetId());
            if (t == null) { // 可能中间表存在但是目标表不存在，那就删除中间表作为第一次插入
                target.setCreateTime(new Date());
                this.saveOrUpdate(target);//target就有id了

                TargetUser targetUser = new TargetUser();
                targetUser.setDelete(0);
                targetUser.setTargetId(target.getId());
                targetUser.setUserId(userId);
                targetUserService.save(targetUser);
            } else {
                if (t.getName().equals(target.getName())) {
                    return t.getId();
                } else {
                    //同时删除两个表
                    t.setDelete(1);
                    this.saveOrUpdate(t);
                    one.setDelete(1);
                    targetUserService.saveOrUpdate(one);


                    //插入新目标表
                    target.setCreateTime(t.getCreateTime() == null ? new Date() : t.getCreateTime());
                    target.setUpdateTime(new Date());
                    this.saveOrUpdate(target);

                    TargetUser targetUserNew = new TargetUser();
                    targetUserNew.setDelete(0);
                    targetUserNew.setTargetId(target.getId());
                    targetUserNew.setUserId(userId);
                    targetUserService.save(targetUserNew);
                }
            }


        }
        return target.getId();
    }

    /**
     * 根据目标id查询目标的完成度与各任务完成度
     *
     * @param uid 用户id
     * @param tid 目标id
     * @return
     */
    @Override
    public Start finishedTargetProcess(Long uid, Long tid) throws IOException {

        // 初始化一个存储各任务的完成度
        Map<String, Double> storeTime = new HashMap<>();
        Integer taskTime = 0;
        Integer dealTime = 0;
        // 根据用户id查询待办执行组
        List<Deal> deals = dealClient.list(String.valueOf(uid)).getData();
        List<AbsorbedDeal> abDealByUserId = absorbedDealClient.getAbDealByUserId(String.valueOf(uid));
        // 根据目标id查询任务组
        List<Task> tasks = taskService.getTaskByTargetId(tid);
        // 待办是否与任务相关
        DiretSimilar diretSimilar = new DiretSimilar();
        tasks = new ArrayList<>(new HashSet<>(tasks));
        for (Task task : tasks) { // 10
            storeTime.put(task.getName(), 0D);
            if (task == null || task.getTimeLength() == null) {
                continue;
            }
            Integer sum = 0;
            for (AbsorbedDeal absorbedDeal : abDealByUserId) {
                Optional<Deal> first = deals.stream().filter(dealre -> dealre.getDealId().equals(absorbedDeal.getDealId())).findFirst();
                if (first.equals(Optional.empty())) continue;

                Deal deal = first.get();
//                Deal deal = dealClient.getDealById(String.valueOf(absorbedDeal.getDealId()));

                if (null == deal) continue;
                double similarity = Similarity.conceptSimilarity(
                        deal.getTitle().replaceAll("[^(\\u4e00-\\u9fa5)]", ""),
                        task.getName().replaceAll("[^(\\u4e00-\\u9fa5)]", ""));
                System.out.println("similarity"+similarity);
                if (similarity == 0.0) continue;

                String[] split = absorbedDeal.getAbsorbedDuration().split(":");
                int temp = (Integer.parseInt(split[0]) * 3600 +
                        Integer.parseInt(split[1]) * 60 +
                        Integer.parseInt(split[2]));
                sum += temp;


            }

            // 计算概率 总执行时间 / 任务时间
            BigDecimal doTime = new BigDecimal(sum == 0?1:sum);
            BigDecimal didTime = new BigDecimal(task.getTimeLength() == "0" ? "1" : task.getTimeLength());
            storeTime.put(task.getName(), doTime.divide(didTime, 5, BigDecimal.ROUND_HALF_UP).doubleValue());

            dealTime += sum;
            taskTime += Integer.parseInt(task.getTimeLength());


        }
        BigDecimal bigTaskTime = new BigDecimal(taskTime == 0 ? 1 : taskTime);
        BigDecimal bigDealTime = new BigDecimal(dealTime);
        double re2 = bigDealTime.divide(bigTaskTime, 5, BigDecimal.ROUND_HALF_UP).doubleValue();
//        double targetProcess = re2 >= 1.0 ? 1.0 : re2;
//
        // 得到各任务进度 storeTime 和 目标执行进度 targetProcess
        Start result = Start.builder().targetProcess(re2)
                .targetName(targetService.getById(
                        targetUserService.selectTargetByUserId(uid)
                                .getTargetId()).getName())
                .taskProcess(storeTime)
                .tasks(new ArrayList<>(new HashSet<>(tasks.stream().map(Task::getName).collect(Collectors.toList()))))
                .build();
        return result;
    }
}
